package com.nuc.zyt.framework.beans.factory.support;

import com.nuc.zyt.framework.beans.BeanDefinition;
import com.nuc.zyt.framework.beans.MutablePropertyValues;
import com.nuc.zyt.framework.beans.PropertyValue;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.InputStream;
import java.util.List;

/**
 * @ClassName XmlBeanDefinitionReader
 * @Description TODO
 * @Author 耀酱
 * @Date 2023/6/5 19:45
 * @Version 1.0
 */
// xml文件的解析
public class XmlBeanDefinitionReader implements BeanDefinitionReader{
    // 声明注册表 其子实现类维护了所有的bean对象信息 map结构
    private BeanDefinitionRegistry registry;

    public XmlBeanDefinitionReader(){
        registry = new SimpleBeanDefinitionRegistry();
    }
    // 返回map结构的注册表
    @Override
    public BeanDefinitionRegistry getRegistry() {
        return registry;
    }
    // 加载配置文件
    @Override
    public void loadBeanDefinition(String configLocation) throws Exception{
        // 使用dom4j 进行 xml文件的解析 流程
        /**
         * 创建 SAXReader 对象：通过创建一个 SAXReader 对象来读取 XML 文件。
         *
         * 调用 SAXReader 对象的 read() 方法：将 XML 文件作为输入流传递给 SAXReader 对象的 read() 方法进行解析。
         * 该方法将返回一个 Document 对象，代表整个 XML 文档。
         *
         * 构建节点树：Document 对象实际上是一个根节点及其下属子节点构成的节点树。在解析 XML 文件时，
         * SAXReader 对象将每个节点解析成一个对象，并使用这些对象重构节点树。
         *
         * 通过 Document 对象获取根元素：可以通过调用 getRootElement() 方法从 Document 对象中获得根元素。
         *
         * 遍历节点树：遍历节点树并访问树中的各个节点。可以通过调用树中各个节点提供的方法来获取节点名称、属性值以及子节点列表等信息。
         */
        SAXReader saxReader = new SAXReader();
        // 获取classpath下的资源文件
        InputStream resourceAsStream = XmlBeanDefinitionReader.class.getClassLoader().getResourceAsStream(configLocation);
        Document read = saxReader.read(resourceAsStream); // 将xml封装为整个Document对象
        Element rootElement = read.getRootElement();// 获取文档树根节点
        List<Element> bean = rootElement.elements("bean");
        for (Element element : bean) {
            // 获取 id class
            String id = element.attributeValue("id");
            String aClass = element.attributeValue("class");
            // 封装对象
            BeanDefinition beanDefinition = new BeanDefinition();
            beanDefinition.setId(id);
            beanDefinition.setClassName(aClass);

            MutablePropertyValues mutablePropertyValues = new MutablePropertyValues();
            // 得到所有依赖项
            List<Element> property = element.elements("property");
            for (Element element1 : property) {
                String name = element.attributeValue("name");
                String ref = element.attributeValue("ref");
                String value = element.attributeValue("value");
                PropertyValue propertyValue = new PropertyValue(name,ref,value);
                mutablePropertyValues.addPropertyValue(propertyValue);
            }
            beanDefinition.setPropertyValues(mutablePropertyValues);

            // 添加到注册表 把每个bean都注册到map里
            registry.registerBeanDefinition(id,beanDefinition);
        }

    }
}
